using System.Collections.Generic;
using Arcane.Source.Client;
using Arcane.Source.Combat;
using Arcane.Source.Data;
using Arcane.Source.Utils;
using Godot;

namespace Arcane.Source
{
    public class GameContext : IContext
    {
        public GameOS Os { get; set; }

        private EventStorage<GameContext, IGameEvent> deferedEvents;

        private RushModeData _data;

        private readonly RandomNumberGenerator rng = new();
        public void OnLoad(Msg msg)
        {
            deferedEvents = Os.EventHub.GetOrCreate<GameContext, IGameEvent>();

            if (msg.TryGet<string>("load", out var path) &&
                FileAccess.GetFileAsBytes(path) is byte[] bytes &&
                bytes.Length > 0)
            {
                _data = RushModeData.Load(RushModeData.Save.FromBytes(bytes));
                rng.Seed = _data.rngSeed;
                rng.State = _data.rngState;
            }
            else
            {
                var name = msg.TryGet<string>("new", out var levelName) ? levelName : "New Level";

                _data = new()
                {
                    name = name,
                    stage = GameStage.Beginning,
                };
            }

            BeginByCurrentStage();
        }

        public void OnPause()
        {
            _data.rngSeed = rng.Seed;
            _data.rngState = rng.State;
        }

        public void OnTick()
        {
            deferedEvents.ProcessAll(this);
        }

        public void QueueEvent(IGameEvent e, int? deferTick = null)
        {
            deferedEvents.Push(e, deferTick);
        }

        public void PickCharacter()
        {
            var pick = Os.ReplaceView<CharaPickView>("chara_pick");
            pick.LoadCharacters(GameDB.Character.Data);
            // pick.OnPick += chara => QueueEvent(new CharaPickedEvent(chara));
        }

        public void CombatSetup()
        {
            var _ = Os.ReplaceView<CombatSetupView>("combat_setup");
        }

        private void BeginByCurrentStage()
        {
            switch (_data.stage)
            {
                case GameStage.Beginning:
                    PickCharacter();
                    break;
                case GameStage.Combat:
                    CombatSetup();
                    break;
                case GameStage.Rest:
                    break;
                case GameStage.Fin:
                    break;
            }
        }

        public interface IGameEvent : IDeferedEvent<GameContext>;

        public class CharaPickedEvent(StringName chara) : IGameEvent
        {
            public void Process(GameContext ctx)
            {
                ctx._data.player = new()
                {
                    character = chara,
                    level = 1,
                };

                GD.Print($"Oh you picked {chara}");

                ctx.Os.QueueFreeView();

                ctx._data.stage = GameStage.Combat;
                ctx.CombatSetup();
            }
        }

        public class CombatSetupEvent(StringName[] runeIds) : IGameEvent
        {
            public void Process(GameContext ctx)
            {
                ctx.Os.QueueFreeView();
                var combat = new CombatContext();
                ctx.Os.PushContext(combat, Msg.Single("runes", runeIds));
                combat.OnCombatEnd += stats => ctx.Os.EventHub.SendEvent<GameContext, IGameEvent>(new CombatEndEvent(stats));
            }
        }

        public class CombatEndEvent(CombatEndStats stat) : IGameEvent
        {
            public void Process(GameContext ctx)
            {
                if (stat.winnerIndex == 0)
                {
                    GD.Print("Player Win");

                    var view = ctx.Os.ReplaceView<TradeView>("trade");
                    
                }
                else
                {
                    GD.Print("Player Lose");
                    ctx.Os.PopContext();
                }

                GD.Print("With rune eliminate:", string.Join(' ', stat.eliminateCounts));
            }
        }
    }
}